package com.future.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.future.allUtils.enums.RoleEnum;
import com.future.domain.DTO.UserLoginDTO;
import com.future.domain.Result;
import com.future.domain.User;
import com.future.domain.UserRole;
import com.future.mapper.UserMapper;
import com.future.mapper.UserRoleMapper;
import com.future.service.RegisterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import  com.future.allUtils.utils.CacheClient;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import static com.future.allUtils.constants.RedisCacheConstants.CAPTCHA_PREFIX;
import static com.future.allUtils.utils.RegexPatterns.*;

/**
 * @Description:注册方法
 * @Author: huayue
 *
 *
 * 1. 参数校验
 * 2. 校验账号是否已存在
 *    校验邮箱是否已存在
 * 3. 校验验证码
 * 4. 密码加密处理 (使用BCrypt加密)
 * 5. 设置默认值
 * 6. 保存用户信息 (MyBatis-Plus的save方法)
 * 7. 注册成功
 */

@Service
public class RegisterServiceImpl implements RegisterService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @Autowired
    private EmailServiceImpl emailService;
    @Autowired
    private CacheClient CacheClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private UserRoleMapper userRoleMapper;

    @Override
    @Transactional
    public Result register(UserLoginDTO dto) {
        //邮箱格式校验
        if(!dto.getEmail().matches(EMAIL_REGEX)){
            return Result.fail("邮箱格式有误");
        }
        if(!dto.getPassword().matches(PASSWORD_REGEX)){
            return Result.fail("密码格式有误,应为8-20位字母、数字、" +
                    "特殊字符，至少包含大小写字母、数字、特殊字符中的两种");
        }

        //通过枚举校验角色是否有效
        String roleName = dto.getRole();
        RoleEnum roleEnum = RoleEnum.getByRoleName(roleName);
        if (roleEnum == null) {
            return Result.fail("无效的角色类型，请选择：学生、教师、心理医生");
        }

        // 2. 校验邮箱是否已存在
        LambdaQueryWrapper<User> emailWrapper = new LambdaQueryWrapper<>();
        emailWrapper.eq(User::getEmail, dto.getEmail());
        if(userMapper.selectCount(emailWrapper)>0){
            return Result.fail("邮箱已被注册，请更换邮箱");
        }

        // 3. 校验验证码
        String captcha = stringRedisTemplate.opsForValue().get(CAPTCHA_PREFIX + dto.getEmail());
        if(!StringUtils.hasText(captcha)){
            return Result.fail("验证码错误");
        }
        if(!captcha.equals(dto.getCaptcha())){
            return Result.fail("验证码错误");
        }

        //设置默认值
        User u=new User();
        u.setEmail(dto.getEmail());
        u.setAvatar("http://47.110.147.12:19000/picture/e7c51c44bec34d289d3222c450c4e0c1.png");


        //3.Bcrypt密码加密
        u.setPassword(bCryptPasswordEncoder.encode(dto.getPassword()));
        userMapper.insert(u);

        //4.将user的身份插入user_role表
        //通过枚举获取角色ID，插入user_role表
        UserRole userRole = new UserRole();
        userRole.setUserId(u.getId());
        userRole.setRoleId(roleEnum.getRoleId());
        userRole.setCreatedAt(LocalDateTime.now());
        userRoleMapper.insert(userRole);

        return  Result.ok();
    }

    @Override
    public Result sendCaptcha(String email) {
        //校验上一次发送的验证码是否未过期
        String captchaKey = CAPTCHA_PREFIX + email;
        String hasCaptcha = stringRedisTemplate.opsForValue().get(captchaKey);
        Long expireSeconds = stringRedisTemplate.getExpire(captchaKey, TimeUnit.SECONDS);
        // 检查 Redis 中是否存在未过期的验证码
        if (StringUtils.hasText(hasCaptcha)) {
            // 存在则说明上一次发送的验证码未过期
            return Result
            .fail("上一次发送的验证码未过期，请"+expireSeconds+"秒后再尝试");
        }


        // 生成验证码   String code = RandomUtil.randomNumbers(6);这个挺好
        Random random = new Random();
        int codeNum = random.nextInt(9000) + 1000;

        //验证码存入redis
        stringRedisTemplate.opsForValue().set(CAPTCHA_PREFIX+email,codeNum+"",60, TimeUnit.SECONDS);

        emailService.sendMail(email,"【心芽】官方","【心芽】"+" 验证码："+codeNum+"，1分钟内有效，请勿泄露给他人");
        return Result.ok();
    }
}
